#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
UI组件定义，包括按钮、输入框等
"""

import pygame
import os
import sys
from bilibili_downloader.ui.theme import *

def get_chinese_font(size):
    """
    获取支持中文的字体
    
    Args:
        size: 字体大小
    
    Returns:
        pygame.font.Font: 支持中文的字体对象
    """
    # 直接使用系统中已知支持中文的字体
    available_fonts = pygame.font.get_fonts()
    
    # 查找第一个可用的中文字体
    for font_name in CHINESE_FONTS:
        if font_name in available_fonts:
            return pygame.font.SysFont(font_name, size)
    
    # 如果没有找到支持中文的字体，使用系统默认字体
    return pygame.font.SysFont(None, size)

class Button:
    """按钮组件"""
    
    def __init__(self, x, y, width, height, text, color=BLUE, hover_color=LIGHT_BLUE, text_color=WHITE):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.text_color = text_color
        self.current_color = color
        self.font = get_chinese_font(FONT_MEDIUM)
        self.is_hovered = False
        
    def draw(self, surface):
        """绘制按钮"""
        pygame.draw.rect(surface, self.current_color, self.rect, border_radius=5)
        text_surface = self.font.render(self.text, True, self.text_color)
        text_rect = text_surface.get_rect(center=self.rect.center)
        surface.blit(text_surface, text_rect)
        
    def update(self, mouse_pos):
        """更新按钮状态"""
        self.is_hovered = self.rect.collidepoint(mouse_pos)
        self.current_color = self.hover_color if self.is_hovered else self.color
        
    def is_clicked(self, event):
        """检查按钮是否被点击"""
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            return self.is_hovered
        return False


class InputBox:
    """输入框组件"""
    
    def __init__(self, x, y, width, height, text='', placeholder='', show_clear_button=False):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.placeholder = placeholder
        self.font = get_chinese_font(FONT_MEDIUM)
        self.active = False
        self.color = GRAY
        self.active_color = BLACK
        self.text_color = BLACK
        self.placeholder_color = DARK_GRAY
        self.cursor_visible = True
        self.cursor_timer = 0
        self.cursor_position = len(text)  # 光标位置
        
        # 清空按钮
        self.show_clear_button = show_clear_button
        if show_clear_button:
            clear_size = height - 10
            self.clear_button_rect = pygame.Rect(x + width - clear_size - 5, y + 5, clear_size, clear_size)
            self.clear_button_hovered = False
        
    def handle_event(self, event):
        """处理输入事件"""
        result = None
        
        # 处理鼠标点击
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:  # 左键点击
            # 检查是否点击了清空按钮
            if self.show_clear_button and self.text and self.clear_button_rect.collidepoint(event.pos):
                self.clear_text()
                return result
            
            # 如果用户点击了输入框，则激活
            was_active = self.active
            self.active = self.rect.collidepoint(event.pos)
            self.color = self.active_color if self.active else GRAY
            
            # 如果刚激活，重置光标闪烁
            if not was_active and self.active:
                self.cursor_visible = True
                self.cursor_timer = 0
        
        # 处理键盘输入
        if event.type == pygame.KEYDOWN and self.active:
            if event.key == pygame.K_RETURN:
                # 回车键提交
                result = self.text
            elif event.key == pygame.K_BACKSPACE:
                # 退格键删除
                if self.cursor_position > 0:
                    self.text = self.text[:self.cursor_position-1] + self.text[self.cursor_position:]
                    self.cursor_position -= 1
            elif event.key == pygame.K_DELETE:
                # 删除键删除光标后的字符
                if self.cursor_position < len(self.text):
                    self.text = self.text[:self.cursor_position] + self.text[self.cursor_position+1:]
            elif event.key == pygame.K_LEFT:
                # 左箭头移动光标
                self.cursor_position = max(0, self.cursor_position - 1)
            elif event.key == pygame.K_RIGHT:
                # 右箭头移动光标
                self.cursor_position = min(len(self.text), self.cursor_position + 1)
            elif event.key == pygame.K_HOME:
                # Home键移动到开头
                self.cursor_position = 0
            elif event.key == pygame.K_END:
                # End键移动到结尾
                self.cursor_position = len(self.text)
            elif event.key == pygame.K_v and pygame.key.get_mods() & pygame.KMOD_CTRL:
                # Ctrl+V 粘贴
                try:
                    # 使用tkinter获取剪贴板内容
                    import tkinter as tk
                    root = tk.Tk()
                    root.withdraw()  # 隐藏窗口
                    
                    try:
                        clipboard_text = root.clipboard_get()
                        if clipboard_text:
                            # 在光标位置插入文本
                            self.text = self.text[:self.cursor_position] + clipboard_text + self.text[self.cursor_position:]
                            self.cursor_position += len(clipboard_text)
                    except:
                        pass  # 剪贴板为空或格式不支持
                    
                    root.destroy()
                except Exception as e:
                    print(f"粘贴错误: {str(e)}")
            else:
                # 添加字符
                try:
                    char = event.unicode
                    if char and ord(char) >= 32:  # 确保是可打印字符
                        # 在光标位置插入字符
                        self.text = self.text[:self.cursor_position] + char + self.text[self.cursor_position:]
                        self.cursor_position += len(char)
                except Exception as e:
                    print(f"输入错误: {str(e)}")
            
            # 重置光标闪烁
            self.cursor_visible = True
            self.cursor_timer = 0
        
        return result
    
    def update(self, dt=1/60, mouse_pos=None):
        """更新光标闪烁状态和清空按钮状态"""
        if self.active:
            self.cursor_timer += dt
            if self.cursor_timer >= 0.5:  # 每0.5秒闪烁一次
                self.cursor_visible = not self.cursor_visible
                self.cursor_timer = 0
        
        # 更新清空按钮悬停状态
        if self.show_clear_button and mouse_pos:
            self.clear_button_hovered = self.clear_button_rect.collidepoint(mouse_pos)
    
    def clear_text(self):
        """清空文本"""
        self.text = ""
        self.cursor_position = 0
    
    def draw(self, surface):
        """绘制输入框"""
        # 绘制输入框背景和边框
        pygame.draw.rect(surface, WHITE, self.rect, 0, border_radius=5)
        pygame.draw.rect(surface, self.color, self.rect, 2, border_radius=5)
        
        # 准备要显示的文本
        display_text = self.text if self.text else self.placeholder
        text_color = self.text_color if self.text else self.placeholder_color
        
        # 计算文本位置
        padding = 5
        text_y = self.rect.y + (self.rect.height - self.font.get_height()) // 2
        
        # 如果有清空按钮，需要减少文本区域宽度
        max_width = self.rect.width - 2 * padding
        if self.show_clear_button and self.text:
            max_width -= self.clear_button_rect.width + 5
        
        # 计算光标位置前的文本
        if self.text:
            cursor_text = self.text[:self.cursor_position]
            cursor_surface = self.font.render(cursor_text, True, text_color)
            cursor_width = cursor_surface.get_width()
            
            # 如果光标位置超出可见区域，调整显示的文本
            if cursor_width > max_width:
                # 从光标位置向前找到可以显示的文本
                test_text = self.text[self.cursor_position-1:self.cursor_position]
                i = self.cursor_position - 2
                while i >= 0 and self.font.render(test_text, True, text_color).get_width() < max_width:
                    test_text = self.text[i:self.cursor_position]
                    i -= 1
                display_text = test_text
                cursor_width = self.font.render(display_text, True, text_color).get_width()
            else:
                # 显示从开始到光标位置后尽可能多的文本
                remaining_width = max_width - cursor_width
                i = self.cursor_position
                test_text = display_text
                while i < len(self.text) and self.font.render(test_text + self.text[i], True, text_color).get_width() <= max_width:
                    test_text += self.text[i]
                    i += 1
                display_text = test_text
        
        # 渲染文本
        text_surface = self.font.render(display_text, True, text_color)
        surface.blit(text_surface, (self.rect.x + padding, text_y))
        
        # 如果输入框处于活动状态且光标可见，绘制光标
        if self.active and self.cursor_visible and self.text:
            # 计算光标在屏幕上的位置
            if self.cursor_position > 0:
                cursor_text = display_text[:min(self.cursor_position, len(display_text))]
                cursor_surface = self.font.render(cursor_text, True, text_color)
                cursor_x = self.rect.x + padding + cursor_surface.get_width()
            else:
                cursor_x = self.rect.x + padding
            
            # 绘制光标
            cursor_height = self.font.get_height()
            pygame.draw.line(surface, BLACK, 
                            (cursor_x, text_y), 
                            (cursor_x, text_y + cursor_height), 
                            2)
        
        # 如果有清空按钮且有文本，绘制清空按钮
        if self.show_clear_button and self.text:
            # 绘制圆形按钮背景
            button_color = LIGHT_BLUE if self.clear_button_hovered else GRAY
            pygame.draw.ellipse(surface, button_color, self.clear_button_rect)
            
            # 绘制X形
            x_center = self.clear_button_rect.centerx
            y_center = self.clear_button_rect.centery
            size = self.clear_button_rect.width // 3
            
            # 绘制X的两条线
            pygame.draw.line(surface, WHITE, 
                            (x_center - size, y_center - size), 
                            (x_center + size, y_center + size), 
                            2)
            pygame.draw.line(surface, WHITE, 
                            (x_center + size, y_center - size), 
                            (x_center - size, y_center + size), 
                            2)


class LogArea:
    """日志显示区域"""
    
    def __init__(self, x, y, width, height):
        self.rect = pygame.Rect(x, y, width, height)
        self.logs = []
        self.font = get_chinese_font(FONT_SMALL)
        self.line_height = FONT_SMALL + 2
        self.max_lines = height // self.line_height  # 估算可显示的最大行数
        self.scroll_offset = 0
        self.auto_scroll = True  # 是否自动滚动到底部
        self.padding = 5
        self.max_width = width - 2 * self.padding  # 文本最大宽度
        
    def add_log(self, message, level="INFO"):
        """添加日志"""
        if level == "ERROR":
            color = RED
        elif level == "SUCCESS":
            color = GREEN
        else:
            color = BLACK
        
        # 处理长消息，按宽度拆分成多行
        wrapped_lines = self._wrap_text(message, self.max_width)
        
        for line in wrapped_lines:
            self.logs.append((line, color))
        
        # 如果启用了自动滚动，则滚动到底部
        if self.auto_scroll and len(self.logs) > self.max_lines:
            self.scroll_offset = len(self.logs) - self.max_lines
    
    def _wrap_text(self, text, max_width):
        """将文本按宽度换行"""
        lines = []
        # 首先按换行符分割
        for line in text.split('\n'):
            if not line:
                lines.append('')
                continue
                
            # 测量当前行宽度
            line_surface = self.font.render(line, True, BLACK)
            if line_surface.get_width() <= max_width:
                lines.append(line)
            else:
                # 需要换行
                current_line = ""
                for char in line:
                    test_line = current_line + char
                    test_surface = self.font.render(test_line, True, BLACK)
                    if test_surface.get_width() <= max_width:
                        current_line = test_line
                    else:
                        lines.append(current_line)
                        current_line = char
                if current_line:  # 添加最后一行
                    lines.append(current_line)
        
        return lines
    
    def draw(self, surface):
        """绘制日志区域"""
        # 绘制背景
        pygame.draw.rect(surface, LIGHT_GRAY, self.rect, 0, border_radius=5)
        pygame.draw.rect(surface, GRAY, self.rect, 2, border_radius=5)
        
        # 绘制日志文本
        visible_logs = self.logs[self.scroll_offset:self.scroll_offset + self.max_lines]
        for i, (log, color) in enumerate(visible_logs):
            text_surface = self.font.render(log, True, color)
            surface.blit(text_surface, (self.rect.x + self.padding, self.rect.y + self.padding + i * self.line_height))
        
        # 如果有滚动条，绘制滚动条
        if len(self.logs) > self.max_lines:
            # 计算滚动条高度和位置
            scroll_height = min(self.rect.height * self.max_lines / len(self.logs), self.rect.height)
            scroll_pos = self.rect.height * self.scroll_offset / len(self.logs)
            
            # 绘制滚动条背景
            scroll_bg_rect = pygame.Rect(
                self.rect.right - 10, 
                self.rect.y, 
                10, 
                self.rect.height
            )
            pygame.draw.rect(surface, GRAY, scroll_bg_rect, 0, border_radius=3)
            
            # 绘制滚动条
            scroll_rect = pygame.Rect(
                self.rect.right - 8, 
                self.rect.y + scroll_pos, 
                6, 
                scroll_height
            )
            pygame.draw.rect(surface, DARK_GRAY, scroll_rect, 0, border_radius=3)
    
    def handle_event(self, event):
        """处理滚动事件"""
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                if event.button == 4:  # 滚轮向上
                    self.scroll_offset = max(0, self.scroll_offset - 3)
                    self.auto_scroll = False  # 用户手动滚动时禁用自动滚动
                elif event.button == 5:  # 滚轮向下
                    max_offset = max(0, len(self.logs) - self.max_lines)
                    self.scroll_offset = min(max_offset, self.scroll_offset + 3)
                    # 如果滚动到底部，重新启用自动滚动
                    if self.scroll_offset >= max_offset:
                        self.auto_scroll = True


class ProgressBar:
    """进度条组件"""
    
    def __init__(self, x, y, width, height):
        self.rect = pygame.Rect(x, y, width, height)
        self.progress = 0  # 0 到 1 之间的值
        self.font = get_chinese_font(FONT_SMALL)
        
    def update(self, progress):
        """更新进度"""
        self.progress = max(0, min(1, progress))  # 确保进度在0-1之间
        
    def draw(self, surface):
        """绘制进度条"""
        # 绘制背景
        pygame.draw.rect(surface, LIGHT_GRAY, self.rect, 0, border_radius=5)
        
        # 绘制进度
        progress_width = int(self.rect.width * self.progress)
        if progress_width > 0:
            progress_rect = pygame.Rect(self.rect.x, self.rect.y, progress_width, self.rect.height)
            pygame.draw.rect(surface, GREEN, progress_rect, 0, border_radius=5)
        
        # 绘制边框
        pygame.draw.rect(surface, GRAY, self.rect, 2, border_radius=5)
        
        # 绘制百分比文本
        percent_text = f"{int(self.progress * 100)}%"
        text_surface = self.font.render(percent_text, True, BLACK)
        text_rect = text_surface.get_rect(center=self.rect.center)
        surface.blit(text_surface, text_rect)